#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPainter>
#include <QBitmap>
#include <QApplication>
#include <QDir>
#include <QFile>
#include <QMessageBox>
#include <QTextStream>
#include "qlvlcolourdialog.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QFile file(qApp->applicationDirPath() + "/" + sLevelFile);
    if (!file.exists())
        QMessageBox::warning(this, "Error", "\"" + sLevelFile + "\" not found!\nMust be placed in program directory!");
    else
    {
        file.open(QIODevice::ReadOnly);
        file.read(robolev, iFileSize);
        file.close();
    }

    ui->levelView->MainWin = this;

    LoadAllTiles();

    QString Line;
    QFile names(qApp->applicationDirPath() + "/names.txt");
    if (!names.exists())
        QMessageBox::warning(this, "Error", "\"names.txt\" not found!\nMust be placed in program directory!");
    else
    {
        names.open(QIODevice::ReadOnly);
        Line = QString(names.readLine()).trimmed();
        while (Line != "")
        {
            Names.append(Line);
            Line = QString(names.readLine()).trimmed();
        }
        names.close();
    }

    QListWidgetItem *Item;

    for (int i = 0; i < 266; i++)
    {
        if ((i == 0x33) || (i == 0x34))
            continue;
        if (Tiles[i].width())
        {
            Item = new QListWidgetItem();
            iItemIndexToTile[ui->tileView->count()] = i;
            if (ui->tileView->count() < Names.count())
                Item->setText(Names.at(ui->tileView->count()));
            else
                Item->setText(QString("0x%1").arg(i, 2, 16, QChar('0')));
            Item->setIcon(QIcon(Tiles[i]));
            ui->tileView->addItem(Item);
        }
    }

    ui->levelView->iCurrentLevel = 0;
    for (int i = 0; i < iBytesPerLevel; i++)
        ui->levelView->CurrentLevel[i] = robolev[i + (0 * iBytesPerLevel)];

    ui->levelView->updateView();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_btnResetLvl_clicked()
{
    if (!ui->levelView->bLevelChanged)
        return;

    int iLevel = ui->spinBox->value();
    for (int i = 0; i < iBytesPerLevel; i++)
        ui->levelView->CurrentLevel[i] = robolev[i + (iLevel * iBytesPerLevel)];

    ui->levelView->bLevelChanged = false;
    ui->levelView->updateView();
}

void MainWindow::on_btnSaveFile_clicked()
{
    if (ui->levelView->bLevelChanged)
        for (int i = 0; i < iBytesPerLevel; i++)
            robolev[i + (ui->levelView->iCurrentLevel * iBytesPerLevel)] = ui->levelView->CurrentLevel[i];

    QFile file(qApp->applicationDirPath() + "/" + sLevelFile);
    file.open(QIODevice::WriteOnly);
    file.write(robolev, iFileSize);
    file.close();
}

void MainWindow::on_spinBox_valueChanged(int iLevel)
{
    ChangeLevel(iLevel);
}

void MainWindow::on_ckbExit_clicked()
{
    ui->levelView->updateView();
}

void MainWindow::on_ckbBoards_clicked()
{
    ui->levelView->updateView();
}

void MainWindow::on_ckbColours_clicked()
{
    ui->levelView->updateView();
}

void MainWindow::on_btnColours_clicked()
{
    //QMessageBox::warning(this, "Error", "Fenster fehlt");
    QLvlColourDialog clDialog(this);
    unsigned char cFGColour = ui->levelView->ColourToHex(ui->levelView->LevelForegroundColour);
    unsigned char cBGColour = ui->levelView->ColourToHex(ui->levelView->LevelBackgroundColour);
    clDialog.setColours(cFGColour, cBGColour);

    int iResult = clDialog.exec();
    if (iResult)
    {
        cFGColour = (iResult-1) / 0x100;
        cBGColour = (iResult-1) % 0x100;
        ui->levelView->LevelForegroundColour = ui->levelView->HexToColour(cFGColour);
        ui->levelView->LevelBackgroundColour = ui->levelView->HexToColour(cBGColour);
        ui->levelView->bLevelChanged = true;
        ui->levelView->CurrentLevel[iLevelColourOffset] = cFGColour;
        ui->levelView->CurrentLevel[iLevelColourOffset + 1] = cBGColour;
        ui->levelView->updateView();
    }
}

void MainWindow::ChangeLevel(int iLevel)
{
    if (ui->levelView->bLevelChanged)
        for (int i = 0; i < iBytesPerLevel; i++)
            robolev[i + (ui->levelView->iCurrentLevel * iBytesPerLevel)] = ui->levelView->CurrentLevel[i];

    for (int i = 0; i < iBytesPerLevel; i++)
        ui->levelView->CurrentLevel[i] = robolev[i + (iLevel * iBytesPerLevel)];
    ui->levelView->iCurrentLevel = iLevel;

    ui->levelView->bLevelChanged = false;
    ui->levelView->updateView();
}

void MainWindow::LoadAllTiles()
{
    QDir TilesDir = QDir(qApp->applicationDirPath() + "/" + sTilePath);
    QStringList files;
    QString sNumber;
    int iTileNo;
    bool ok;

    if (!TilesDir.exists())
    {
        QMessageBox::warning(this, "Error", "\"" + sTilePath + "\" subdirectory not found!");
        return;
    }

    files = TilesDir.entryList(QStringList("*.bmp"), QDir::Files | QDir::NoSymLinks);
    for (int i = 0; i < files.size(); i++)
    {
        sNumber = files.at(i);
        sNumber.truncate(2);
        iTileNo = sNumber.toInt(&ok, 16);
        if (ok)
        {
            Tiles[iTileNo].load(qApp->applicationDirPath() + "/" + sTilePath + "/" + files.at(i));
            if ((iTileNo >= 0xC8) && (iTileNo <= 0xFF))
                Tiles[iTileNo] = Tiles[iTileNo].createMaskFromColor(Qt::white, Qt::MaskInColor);
        }

        if (files.at(i) == "door.bmp")
            Tiles[iDoorTile].load(qApp->applicationDirPath() + "/" + sTilePath + "/" + files.at(i));
        if (files.at(i) == "board1.bmp")
            Tiles[iBoard1Tile].load(qApp->applicationDirPath() + "/" + sTilePath + "/" + files.at(i));
        if (files.at(i) == "board2.bmp")
            Tiles[iBoard2Tile].load(qApp->applicationDirPath() + "/" + sTilePath + "/" + files.at(i));
        if (files.at(i) == "board3.bmp")
            Tiles[iBoard3Tile].load(qApp->applicationDirPath() + "/" + sTilePath + "/" + files.at(i));
        if (files.at(i) == "board4.bmp")
            Tiles[iBoard4Tile].load(qApp->applicationDirPath() + "/" + sTilePath + "/" + files.at(i));
        if (files.at(i) == "board5.bmp")
            Tiles[iBoard5Tile].load(qApp->applicationDirPath() + "/" + sTilePath + "/" + files.at(i));
    }
}

void MainWindow::on_btnB1Del_clicked()
{
    ui->levelView->deleteBoard(0);
}

void MainWindow::on_btnB2Del_clicked()
{
    ui->levelView->deleteBoard(1);
}

void MainWindow::on_btnB3Del_clicked()
{
    ui->levelView->deleteBoard(2);
}

void MainWindow::on_btnB4Del_clicked()
{
    ui->levelView->deleteBoard(3);
}

void MainWindow::on_btnB5Del_clicked()
{
    ui->levelView->deleteBoard(4);
}

void MainWindow::onSizeChanged(int Index, int iBoard)
{
    if ((Index + 0x33) != ui->levelView->Boards[iBoard].iTile)
    {
        ui->levelView->Boards[iBoard].iTile = Index + 0x33;
        if (Index == 0)
            ui->levelView->Boards[iBoard].iWidth = 0x0F;
        else
            ui->levelView->Boards[iBoard].iWidth = 0x1B;
        ui->levelView->Boards[iBoard].iWidthPixel = 2*ui->levelView->Boards[iBoard].iWidth;
        if (!ui->levelView->bLevelChanged)
            ui->levelView->bLevelChanged = true;
        ui->levelView->boardsChanged(iBoard);
    }
}

void MainWindow::on_cmbB1Size_currentIndexChanged(int i)
{
    onSizeChanged(i, 0);
}

void MainWindow::on_cmbB2Size_currentIndexChanged(int i)
{
    onSizeChanged(i, 1);
}

void MainWindow::on_cmbB3Size_currentIndexChanged(int i)
{
    onSizeChanged(i, 2);
}

void MainWindow::on_cmbB4Size_currentIndexChanged(int i)
{
    onSizeChanged(i, 3);
}

void MainWindow::on_cmbB5Size_currentIndexChanged(int i)
{
    onSizeChanged(i, 4);
}

void MainWindow::onTypeChanged(int Index, int iBoard, int iDist)
{
    if ((Index + 1) != ui->levelView->Boards[iBoard].iType)
    {
        ui->levelView->Boards[iBoard].iType = Index + 1;
        if (Index < 3)
            ui->levelView->Boards[iBoard].iDist = 0;

        if (Index >= 3)
        {
            ui->levelView->Boards[iBoard].iDist = iDist;
            ui->levelView->Boards[iBoard].iDistPixel = 2 * iDist;
        }

        switch (Index+1)
        {
            case 0x01: ui->levelView->Boards[iBoard].iDistPixel = 13 * iTileSize; break;
            case 0x02: ui->levelView->Boards[iBoard].iDistPixel = 14 * iTileSize + 6; break;
            case 0x03: ui->levelView->Boards[iBoard].iDistPixel = 9 * iTileSize; break;
            case 0x06: ui->levelView->Boards[iBoard].iDistPixel = ui->levelView->Boards[iBoard].iDistPixel*5 - 5; break;
        }

        if (!ui->levelView->bLevelChanged)
            ui->levelView->bLevelChanged = true;
        ui->levelView->boardsChanged(iBoard);
    }
}

void MainWindow::on_cmbB1Type_currentIndexChanged(int i)
{
    onTypeChanged(i, 0, ui->spnB1Dist->value());
}

void MainWindow::on_cmbB2Type_currentIndexChanged(int i)
{
    onTypeChanged(i, 1, ui->spnB2Dist->value());
}

void MainWindow::on_cmbB3Type_currentIndexChanged(int i)
{
    onTypeChanged(i, 2, ui->spnB3Dist->value());
}

void MainWindow::on_cmbB4Type_currentIndexChanged(int i)
{
    onTypeChanged(i, 3, ui->spnB4Dist->value());
}

void MainWindow::on_cmbB5Type_currentIndexChanged(int i)
{
    onTypeChanged(i, 4, ui->spnB5Dist->value());
}

void MainWindow::onDistChanged(int Value, int iBoard, int iType)
{
    if (iType < 3)
        return;

    if (Value != ui->levelView->Boards[iBoard].iDist)
    {
        ui->levelView->Boards[iBoard].iDist = Value;
        ui->levelView->Boards[iBoard].iDistPixel = 2*Value;

        switch (iType+1)
        {
            case 0x01: ui->levelView->Boards[iBoard].iDistPixel = 13 * iTileSize; break;
            case 0x02: ui->levelView->Boards[iBoard].iDistPixel = 14 * iTileSize + 6; break;
            case 0x03: ui->levelView->Boards[iBoard].iDistPixel = 9 * iTileSize; break;
            case 0x06: ui->levelView->Boards[iBoard].iDistPixel = ui->levelView->Boards[iBoard].iDistPixel*5 - 5; break;
        }

        if (!ui->levelView->bLevelChanged)
            ui->levelView->bLevelChanged = true;
        ui->levelView->boardsChanged(iBoard);
    }
}

void MainWindow::on_spnB1Dist_valueChanged(int i)
{
    onDistChanged(i, 0, ui->cmbB1Type->currentIndex());
}

void MainWindow::on_spnB2Dist_valueChanged(int i)
{
    onDistChanged(i, 1, ui->cmbB2Type->currentIndex());
}

void MainWindow::on_spnB3Dist_valueChanged(int i)
{
    onDistChanged(i, 2, ui->cmbB3Type->currentIndex());
}

void MainWindow::on_spnB4Dist_valueChanged(int i)
{
    onDistChanged(i, 3, ui->cmbB4Type->currentIndex());
}

void MainWindow::on_spnB5Dist_valueChanged(int i)
{
    onDistChanged(i, 4, ui->cmbB5Type->currentIndex());
}

void MainWindow::onDelayChanged(int Value, int iBoard)
{
    if (Value != ui->levelView->Boards[iBoard].iDelay)
    {
        ui->levelView->Boards[iBoard].iDelay = Value;

        if (!ui->levelView->bLevelChanged)
            ui->levelView->bLevelChanged = true;
        ui->levelView->boardsChanged(iBoard);
    }
}

void MainWindow::on_spnB1Delay_valueChanged(int i)
{
    onDelayChanged(i, 0);
}

void MainWindow::on_spnB2Delay_valueChanged(int i)
{
    onDelayChanged(i, 1);
}

void MainWindow::on_spnB3Delay_valueChanged(int i)
{
    onDelayChanged(i, 2);
}

void MainWindow::on_spnB4Delay_valueChanged(int i)
{
    onDelayChanged(i, 3);
}

void MainWindow::on_spnB5Delay_valueChanged(int i)
{
    onDelayChanged(i, 4);
}

void MainWindow::onStopChanged(int Index, int iBoard)
{
    if (Index != ui->levelView->Boards[iBoard].iStop)
    {
        ui->levelView->Boards[iBoard].iStop = Index;

        if (!ui->levelView->bLevelChanged)
            ui->levelView->bLevelChanged = true;
        ui->levelView->boardsChanged(iBoard);
    }
}

void MainWindow::on_cmbB1Stop_currentIndexChanged(int i)
{
    onStopChanged(i, 0);
}

void MainWindow::on_cmbB2Stop_currentIndexChanged(int i)
{
    onStopChanged(i, 1);
}

void MainWindow::on_cmbB3Stop_currentIndexChanged(int i)
{
    onStopChanged(i, 2);
}

void MainWindow::on_cmbB4Stop_currentIndexChanged(int i)
{
    onStopChanged(i, 3);
}

void MainWindow::on_cmbB5Stop_currentIndexChanged(int i)
{
    onStopChanged(i, 4);
}

void MainWindow::onRevChanged(bool Checked, int iBoard)
{
    if (((int)Checked * 0x24) != ui->levelView->Boards[iBoard].iRev)
    {
        ui->levelView->Boards[iBoard].iRev = (int)Checked * 0x24;

        if (!ui->levelView->bLevelChanged)
            ui->levelView->bLevelChanged = true;
        ui->levelView->boardsChanged(iBoard);
    }
}

void MainWindow::on_ckbB1Rev_toggled(bool bChecked)
{
    onRevChanged(bChecked, 0);
}

void MainWindow::on_ckbB2Rev_toggled(bool bChecked)
{
    onRevChanged(bChecked, 1);
}

void MainWindow::on_ckbB3Rev_toggled(bool bChecked)
{
    onRevChanged(bChecked, 2);
}

void MainWindow::on_ckbB4Rev_toggled(bool bChecked)
{
    onRevChanged(bChecked, 3);
}

void MainWindow::on_ckbB5Rev_toggled(bool bChecked)
{
    onRevChanged(bChecked, 4);
}
